package com.example.yqand4v1_1.utils;

public class SnowflakeIDGenerator {
    private static final long EPOCH = 1609459200000L; // 2021-01-01 00:00:00 UTC
    private static final int MACHINE_BITS = 5;
    private static final int SEQUENCE_BITS = 12;
    private static final int MAX_MACHINE_ID = (1 << MACHINE_BITS) - 1;
    private static final int MAX_SEQUENCE = (1 << SEQUENCE_BITS) - 1;

    private final long machineId;
    private long lastTimestamp = -1;
    private long sequence = 0;

    public SnowflakeIDGenerator(long machineId) {
        if (machineId < 0 || machineId > MAX_MACHINE_ID) {
            throw new IllegalArgumentException("Machine ID must be between 0 and " + MAX_MACHINE_ID);
        }
        this.machineId = machineId;
    }

    public synchronized long generateID() {
        long currentTimestamp = System.currentTimeMillis() - EPOCH;

        if (currentTimestamp < lastTimestamp) {
            throw new IllegalStateException("Clock moved backwards. Refusing to generate an ID.");
        }

        if (currentTimestamp == lastTimestamp) {
            sequence = (sequence + 1) & MAX_SEQUENCE;
            if (sequence == 0) {
                currentTimestamp = waitNextMillis(currentTimestamp);
            }
        } else {
            sequence = 0;
        }

        lastTimestamp = currentTimestamp;

        return (currentTimestamp << (MACHINE_BITS + SEQUENCE_BITS))
                | (machineId << SEQUENCE_BITS)
                | sequence;
    }

    private long waitNextMillis(long lastTimestamp) {
        long currentTimestamp;
        do {
            currentTimestamp = System.currentTimeMillis() - EPOCH;
        } while (currentTimestamp <= lastTimestamp);
        return currentTimestamp;
    }

    public long generateIDWithBitLimit(int bitLimit) {
        if (bitLimit <= 0 || bitLimit > 63) {
            throw new IllegalArgumentException("Bit limit must be between 1 and 63.");
        }

        String fullID = generateID()+"";
      //  System.out.println(fullID);
         String id = fullID.substring(fullID.length()-bitLimit,fullID.length());
       // System.out.println(id);

        return Long.valueOf(id);
    }





}
